#ifndef FND_GAME_PHYSICS_H_
#define FND_GAME_PHYSICS_H_

// Math and base include
#include <Common/Base/hkBase.h>
#include <Common/Base/hkBase.h>
#include <Common/Base/System/hkBaseSystem.h>
#include <Common/Base/Memory/hkThreadMemory.h>
#include <Common/Base/Memory/Memory/Pool/hkPoolMemory.h>
#include <Common/Base/System/Error/hkDefaultError.h>
#include <Common/Base/Monitor/hkMonitorStream.h>

// Dynamics includes
#include <Physics/Collide/hkpCollide.h>										
#include <Physics/Collide/Agent/ConvexAgent/SphereBox/hkpSphereBoxAgent.h>	
#include <Physics/Collide/Shape/Convex/Box/hkpBoxShape.h>					
#include <Physics/Collide/Shape/Convex/Sphere/hkpSphereShape.h>				
#include <Physics/Collide/Dispatch/hkpAgentRegisterUtil.h>					

#include <Physics/Collide/Query/CastUtil/hkpWorldRayCastInput.h>			
#include <Physics/Collide/Query/CastUtil/hkpWorldRayCastOutput.h>			

#include <Physics/Dynamics/World/hkpWorld.h>								
#include <Physics/Dynamics/Entity/hkpRigidBody.h>							
#include <Physics/Utilities/Dynamics/Inertia/hkpInertiaTensorComputer.h>	

#include <Common/Base/Thread/Job/ThreadPool/Cpu/hkCpuJobThreadPool.h>
#include <Common/Base/Thread/Job/ThreadPool/Spu/hkSpuJobThreadPool.h>
#include <Common/Base/Thread/JobQueue/hkJobQueue.h>

// Visual Debugger includes
#include <Common/Visualize/hkVisualDebugger.h>
#include <Physics/Utilities/VisualDebugger/hkpPhysicsContext.h>

// seri
#include <Common/Serialize/Packfile/hkPackfileData.h>



// Engine includes
#include <ltbasedefs.h>
#include <ltengineobjects.h>
#include "RacingCamera.h"


#if defined(HK_PLATFORM_PS3_PPU)
#include <Common/Base/Spu/Util/hkSpuUtil.h>
#include <cell/spurs.h>
#endif

#include <map>


class hkpVehicleInstance ;
class hkpVehicleRayCastWheelCollide ;
class hkpVehicleData ;
class hkpVehicleDefaultAerodynamics ;
class hkpVehicleDefaultSuspension ;
class hkpVehicleDefaultBrake ;
class hkpVehicleDefaultTransmission ;
class hkpTyremarksInfo ;
class hkpVehicleDefaultEngine ;
class hkpVehicleDefaultSteering ;
class hkpVehicleDefaultAnalogDriverInput ;
class hkpConvexVerticesShape ;
class hkpVehicleDefaultVelocityDamper ;
class physics_car_builder ;
class VehicleTyremarks;
class vehicle_phantom;
class VehicleCollisionEvents;
class DriftControllerInterface;

// game logic
class racing_logic_shell ;


typedef std::map<int, vehicle_phantom*> car_phantom_map;
typedef std::map<int, hkpVehicleInstance*> physics_car_map ;



struct car_rigidbody_property
{
	float Mass_car;
	float Friction_car;
	float Restitution_car;
};
void setup_physics_world(hkpWorld* phy) ;

class server_physics
{
public:
    server_physics(racing_logic_shell* shell) ;
    racing_logic_shell* logic_shell() {return m_game_logic ;}
public:
    ~server_physics() ;
    physics_car_map::const_iterator begin() const {return m_cars.begin() ;}
    physics_car_map::const_iterator end() const {return m_cars.end() ;}
    physics_car_map::size_type car_number() const {return m_cars.size();}
    hkpWorld* physics_world() {return m_physicsWorld ;}
    bool build_race_map(const char* fileName) ;
    bool load_world_from_file(const char* fileName) ;
    void update(float inteval) ;
    bool create_a_car(int id, const char* info_name) ;
    bool create_a_car(int id, const std::string& info_name) {return create_a_car(id, info_name.c_str());}
    void build_land_scape() ;
    hkVector4 car_position(int id) ;
    hkReal car_speed(int id) ;
    void deactive_car_from_physics(int id) ;
    void active_car_in_physics(int id) ;
    const hkQuaternion& car_rotation(int id) ;
    void set_the_car_to_absolute_pos_and_rot(int id, const LTVector& pos, const LTRotation& rot) ;
    void car_wheel_pos_rot(int id, int wheel_id, hkVector4& pos, hkQuaternion& rot) ;
    
    void update_cars(float timeInteval) ;
    hkpVehicleInstance* find_car_by_id(int id) ;
    void add_phantom(int id) ;
    hkpShape* load_object_shape_from_file(const char* fileName) ;
    hkpShape* load_object_shapeandproperty_from_file(const char* fileName,car_rigidbody_property* carproperty) ;
    void remove_a_car(int id) ;
    void add_key_to_a_car(int key, int id);
    void steer_car_action(uint32 action,
                          hkReal& x,
                          hkReal& y,
                          hkpVehicleInstance* instance,
                          float y_d,
                          float timeInteval) ;
    
    void steer_car_absolute_action(float inputX,
                                   float inputY,
                                   bool brake,
                                   hkpVehicleInstance* carInstance) ;
    
    void send_car_tyremarks_message() ;
    void handle_car_action(hkpVehicleInstance* carInstace, int id, float timeInteval);
    //void when_car_brake_and_steer(hkpVehicleInstance* carInstace);
    const hkp1dAngularFollowCam::CameraOutput* get_racing_camera_output(hkpVehicleInstance* carInstace);


private:
    void vehicle_drift(float turning, float timeStep, hkpVehicleInstance* carInstance, bool isDriftSpring);
    void create_car_dynamic_parms(hkpVehicleInstance* carInstance);
    void store_car_parms(hkpVehicleInstance* carInstance);
    void restore_car_parms(hkpVehicleInstance* carInstance);
    void send_a_car_tyremarks(physics_car_map::value_type&, ILTMessage_Write*) ;
    void update_car_tyremarks(float time_inteval, hkpVehicleInstance* carInstance, int id) ;
   
    
        
private:
    struct car_parm_save_type
    {
        float SlipAngle[4];
        float Friction[4];
        float ViscosityFriction[4];
    };

    struct racing_camera_type
    {
        RacingCamera RacingCamera;
        hkp1dAngularFollowCam::CameraOutput RacingCameraOutput;
    };

    std::map<hkpVehicleInstance*, car_parm_save_type> m_car_parm_saveback_map;
    std::map<hkpVehicleInstance*, VehicleCollisionEvents*> m_carbody_collision_map; 
    std::map<hkpVehicleInstance*, racing_camera_type*> m_car_physics_camera;
    std::map<int, VehicleTyremarks*> m_tyremarks_map;
	

private:
    racing_logic_shell* m_game_logic ;
    hkPoolMemory* m_memoryManager ;
    hkThreadMemory* m_threadMemory ;
    char* m_stackBuffer ;
    hkJobThreadPool* m_threadPool ;
    hkJobQueue* m_jobQueue ;
    hkpWorld* m_physicsWorld ;
    hkpPhysicsContext* m_context ;
    hkVisualDebugger* m_vdb ;
    hkPackfileData* m_packfileData;
    bool m_isTyremarksGenerated;
    physics_car_builder* m_carBuilder ;
    physics_car_map m_cars;
    car_phantom_map m_carPhantoms;
    int m_dataSend ;
    bool m_isUsingDriftMode;
    
    

private:

} ;

#endif
